<?php
namespace App\Api\Controllers\Merchant;

use App\Models\CustomerappletsAuthorizeAppids;
use App\Models\MerchantStoreAppidSecret;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use EasyWeChat\Factory;
use EasyWeChat\OpenPlatform\Server\Guard;
use App\Api\Controllers\BaseController;
use Illuminate\Auth\Access\AuthorizationException;

class StoreWechatTicketController extends BaseController
{
    protected $wechat_qrcode_rule;  // 微信小程序二维码规则地址
    protected $wechat_pages_url;    // 微信小程序扫码点餐页面地址
    protected $customerAppletsAuthorizeAppid = "customerapplets_authorize_appids";

    public function __construct()
    {
        $this->wechat_pages_url     = 'pages/ordermenu/ordermenu';
        $this->wechat_qrcode_rule   = 'https://test.yunsoyi.cn/applet/applet?store_id=';
    }

    /**
     * 增加/修改二维码规则
     */
    public function createQrcodeRule($input)
    {
        try {
            $component_appid = $this->app_id;
            $authorizer_appid = $input['wechat_appid'];

            // 读取 authorizer_refresh_token
            $customerappletsAuthorizeAppids = new CustomerappletsAuthorizeAppids();
            $infoData['t_appid'] = $component_appid;
            $infoData['AuthorizerAppid'] = $authorizer_appid;
            $info = $customerappletsAuthorizeAppids->getInfo($infoData);
            $authorizer_refresh_token = $info->authorizer_refresh_token;

            // 获取 AuthorizerToken
            $authorizer_access_token = Cache::get($authorizer_appid . '_authorizer_access_token');
            if (empty($authorizer_access_token)) {
                $authorizer_access_token = $this->getAuthorizerAccessToken($component_appid, $authorizer_appid, $authorizer_refresh_token);
            }

            // 获取证书并保存
            $this->getAppletCertificate($authorizer_access_token);

            // 生成二维码链接规则
            $url="https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpadd?access_token=" . $authorizer_access_token;
            $param = array(
                // 注册字段
                "prefix" => $input['prefix'],
                "permit_sub_rule" => 1,
                "path" => $input['pages_url'],
                "open_version" => 3,
                "is_edit" => 0
            );
            $this->curl_post_https($url, json_encode($param));

            // 发布已设置的二维码规则
            $publish_url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumppublish?access_token='  . $authorizer_access_token;
            $publish_param = array(
                // 注册字段
                "prefix" => $input['prefix']
            );
            $this->curl_post_https($publish_url, json_encode($publish_param));
        } catch (\Exception $e) {
            // return $this->sys_response(202, '创建二维码规则失败' . $e->getMessage());
            throw new AuthorizationException('参数未生成，请过1分钟再试', 40000);
        }
    }

    /**
     * 获取小程序证书
     */
    public function getAppletCertificate($authorizer_access_token)
    {
        $dir = 'applet/';
        // 检查存放小程序证书文件夹是否存在
        if (!is_dir(public_path($dir))) {
            mkdir(public_path($dir), 0777);
        }

        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpdownload?access_token=' . $authorizer_access_token;
        $param=array(
            //注册字段
            "prefix" => "https://weixin.qq.com/qrcodejump",
            "permit_sub_rule" => 1,
            "path" => "pages/index/index",
            "open_version" => 3,
            "is_edit" => 0
        );
        $data = json_encode($param);

        $res = $this->curl_post_https($url, $data);
        $res = json_decode($res, true);

        if ($res['errcode'] == 0) {
            $fileName = $res['file_name'];
            $fileContent = $res['file_content'];

            // 判断是否已有该文件
            $files = scandir($dir, 1);
            foreach ($files as $k => $v) {
                if ($v == $fileName) {
                    return $this->sys_response(200, '请求成功');
                }
            }

            // 不存在则保存文件
            // if ($files[0] != $fileName) {
                // 保存路径
                $save_dir = public_path($dir);
                $resource = fopen($save_dir . $fileName , 'a');
                fwrite($resource, $fileContent);
                fclose($resource);
            // }
        } else {
            throw new AuthorizationException('小程序证书获取失败', 40000);
        }
    }

    // 获取 authorizer_access_token
    public function getAuthorizerAccessToken($component_appid,$authorizer_appid,$authorizer_refresh_token){
        //第三方平台接口的调用凭据。令牌的获取是有限制的，每个令牌的有效期为 2 小时
        $component_access_token = Cache::get("component_access_token");
        if(empty($component_access_token)){
            // $component_access_token = $this->getComponentAccessTokenByTicket();
            $this->getComponentAccessTokenByTicket();
            throw new AuthorizationException('component_access_token数据为空,请稍等10分钟再进行尝试', 40000);
        }

        try {
            //如果缓存中有数据，直接读取缓存中的数据
            $authorizer_access_token = Cache::get($authorizer_appid."_authorizer_access_token");

            if($authorizer_access_token){
                return ['status' => 200,'message' => '获取成功','data' => ['authorizer_access_token' => $authorizer_access_token]];
            }
            //否则，再去请求接口
            $componentTokenData = [
                'component_appid'    => $component_appid,
                'authorizer_appid'   => $authorizer_appid,
                'authorizer_refresh_token' => $authorizer_refresh_token
            ];

            $url = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token='.$component_access_token;

            $result = $this->curl_post_https($url,json_encode($componentTokenData));
            $result = json_decode($result, true);

            if(!empty($result['authorizer_access_token']) && isset($result['authorizer_access_token'])){
                //一旦丢失，只能让用户重新授权，才能再次拿到新的刷新令牌
                Cache::put($authorizer_appid.'_authorizer_access_token', $result['authorizer_access_token'], 120);

                //更新该授权方 appid的authorizer_refresh_token
                DB::table($this->customerAppletsAuthorizeAppid)->where(['t_appid' => $component_appid,'AuthorizerAppid' => $authorizer_appid])->update([
                    'authorizer_refresh_token' => $result['authorizer_refresh_token'],
                    'updated_at'               => date("Y-m-d H:i:s",time())
                ]);

                return ['status' => 200,'message' => '获取成功','data' => $result];
            }else{
                throw new AuthorizationException('获取authorizer_access_token失败！', 40000);
            }
        } catch (\Exception $e) {
            throw new AuthorizationException($e->getMessage().' | '.$e->getFile().' | '.$e->getLine(), 40000);
        }
    }

    /**
     * 获取并缓存 component_access_token
     * 令牌（component_access_token）是第三方平台接口的调用凭据
     * @return false|string
     */
    public function getComponentAccessTokenByTicket()
    {
        $config = [
            'app_id'   => $this->app_id,
            'secret'   => $this->secret,
            'token'    => $this->token,
            'aes_key'  => $this->aes_key
        ];

        $openPlatform = Factory::openPlatform($config);
        $server       = $openPlatform->server;

        // VerifyTicket事件
        $server->push(function ($message) use ($config) {
            $getComponentAccessTokenData  = [
                //第三方平台appid
                'component_appid'         => $config['app_id'],
                //第三方平台appsecret
                'component_appsecret'     => $config['secret'],
                //微信后台推送的ticket
                'component_verify_ticket' => $message['ComponentVerifyTicket'],
            ];

            $component_access_token_res = $this->getComponentAccessToken($getComponentAccessTokenData);
            $component_access_token_res = json_decode($component_access_token_res,true);
            if(!empty($component_access_token_res['component_access_token']) && isset($component_access_token_res['component_access_token'])){
                Cache::put('component_access_token', $component_access_token_res['component_access_token'], 110);
            }
        }, Guard::EVENT_COMPONENT_VERIFY_TICKET);

        return Cache::get("component_access_token");
    }

    /**
     * 令牌（component_access_token）是第三方平台接口的调用凭据
     * @param $data
     * @return false|string
     */
    public function getComponentAccessToken($data)
    {
        $requestData  = [
            'component_appid'         => $data['component_appid'],          //第三方平台 appid
            'component_appsecret'     => $data['component_appsecret'],      //第三方平台 appsecret
            'component_verify_ticket' => $data['component_verify_ticket'],  //微信后台推送的 ticket
        ];
        try{
            $url    = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token';
            $result = $this->curl_post_https($url, json_encode($requestData));
            return $result;
        }catch (\Exception $e){
            Log::info("获取微信第三方平台接口调用凭据出错：");
            Log::info($e->getMessage());
        }
    }

    // 暂时没有用到
    public function getAuthorizerRefreshToken(){

        $component_appid = 'wx569476fd97973ad2';
        $authorization_code = 'queryauthcode@@@mcAYqhBWO1Ea5yoHHwEfLOP7X8zvAzuBA5_rjp5qEpMRGAN0zQO3CiTafIrdJtD31rthuE_08iAkEP-hPf1jFQ';
        $component_access_token = Cache::get("component_access_token"); //第三方平台接口的调用凭据。令牌的获取是有限制的，每个令牌的有效期为 2 小时

        if(empty($component_access_token)){
            return ['status' => 40000,'message' => 'component_access_token数据为空,请稍等10分钟再进行尝试'];
        }

        try {
            $componentTokenData = [
                'component_appid'    => $component_appid,
                'authorization_code' => $authorization_code
            ];

            $url    = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token='.$component_access_token;

            $result = $this->curl_post_https($url,json_encode($componentTokenData));

            $result = json_decode($result,true);

            if(!empty($result['authorization_info']) && isset($result['authorization_info'])){
                //一旦丢失，只能让用户重新授权，才能再次拿到新的刷新令牌
//                Cache::put('authorizer_refresh_token', $result['authorization_info']['authorizer_refresh_token'], 3600 * 24 * 30);
                return ['status' => 200,'message' => '获取成功','data' => $result];
            }else{
                // $errmsg = $this->getCodeMessage($result['errcode']);
                return ['status' => $result['errcode'],'message' => $result['errcode'].":".$result['errmsg']];
            }
        } catch (\Exception $e) {
            return ['status' => 40000,'message' => $e->getMessage().' | '.$e->getFile().' | '.$e->getLine()];
        }
    }

}
